

#pragma once

#include "zAdAChar.h"
#include "zAcField.h"
#include "zAcString.h"


class UcDbField;

typedef UcArray<UcDbField*> UcDbFieldArray;

typedef struct UcFd
{

    enum EvalFields
    {
        kEvalRecursive      = (0x1 << 0),       
    };

    enum ConvertFieldToText
    {
        kConvertFieldToTextNone         = 0,
        kEvaluateBeforeConversion       = (0x1 << 0),
        kExcludeEvaluatorsInList        = (0x1 << 1),
        kIgnoreEvaluatorVersion         = (0x1 << 2),
    };

} UcFd;

typedef struct UcHyperlink
{
    UcString                msUrl;
    UcString                msSubLocation;
    UcString                msDescription;
    ZSoft::Int32            mlFlag;

} UcHyperlink;

class UcDbField : public UcDbObject
{
public:
    enum State
    {
        kInitialized        = (0x1 << 0),       
        kCompiled           = (0x1 << 1),       
        kModified           = (0x1 << 2),       
        kEvaluated          = (0x1 << 3),       
        kHasCache           = (0x1 << 4),       
        kHasFormattedString = (0x1 << 5),       
    };

    enum EvalOption
    {
        kDisable            = 0,                
        kOnOpen             = (0x1 << 0),       
        kOnSave             = (0x1 << 1),       
        kOnPlot             = (0x1 << 2),       
        kOnEtransmit        = (0x1 << 3),       
        kOnRegen            = (0x1 << 4),       
        kOnDemand           = (0x1 << 5),       
        kAutomatic          = (kOnOpen | kOnSave | kOnPlot | 
                               kOnEtransmit | kOnRegen | kOnDemand),    
    };

    enum EvalContext
    {
        kOpen               = (0x1 << 0),       
        kSave               = (0x1 << 1),       
        kPlot               = (0x1 << 2),       
        kEtransmit          = (0x1 << 3),       
        kRegen              = (0x1 << 4),       
        kDemand             = (0x1 << 5),       
        kPreview            = (0x1 << 6),       
        kPlotPreview        = (0x1 << 7),
    };

    enum EvalStatus
    {
        kNotYetEvaluated    = (0x1 << 0),       
        kSuccess            = (0x1 << 1),       
        kEvaluatorNotFound  = (0x1 << 2),       
        kSyntaxError        = (0x1 << 3),       
        kInvalidCode        = (0x1 << 4),       
        kInvalidContext     = (0x1 << 5),       
        kOtherError         = (0x1 << 6),       
    };

    enum FieldCodeFlag
    {
        kFieldCode          = (0x1 << 0),       
        kEvaluatedText      = (0x1 << 1),       
        kEvaluatedChildren  = (0x1 << 2),       
        kObjectReference    = (0x1 << 3),       

        kAddMarkers         = (0x1 << 4),       
        kEscapeBackslash    = (0x1 << 5),       
        kStripOptions       = (0x1 << 6),       
        kPreserveFields     = (0x1 << 7),       
        kTextField          = (0x1 << 8),       
        kPreserveOptions    = (0x1 << 9),
        kDetachChildren     = (0x1 << 10),

        kChildObjectReference = (0x1 << 11),

        kForExpression      = (0x1 << 12),

    };

    enum FilingOption
    {
        kSkipFilingResult   = (0x1 << 0),       
    };

public:
    UCDB_DECLARE_MEMBERS(UcDbField);

    UCDB_PORT UcDbField(void);
    UCDB_PORT UcDbField(const ZTCHAR * pszFieldCode, bool bTextField = false);
    UCDB_PORT ~UcDbField(void);

    UCDB_PORT Ucad::ErrorStatus setInObject (UcDbObject* pObj, 
                                             const ZTCHAR * pszPropName);
    UCDB_PORT Ucad::ErrorStatus postInDatabase(UcDbDatabase* pDb);
    UCDB_PORT UcDbField::State state        (void) const;
    UCDB_PORT UcDbField::EvalStatus evaluationStatus(int* pnErrCode = NULL, 
                                             ZTCHAR ** pszErrMsg = NULL) const;
    UCDB_PORT UcDbField::EvalOption evaluationOption(void) const;
    UCDB_PORT Ucad::ErrorStatus setEvaluationOption(UcDbField::EvalOption nEvalOption);
    UCDB_PORT UcDbField::FilingOption filingOption(void) const;
    UCDB_PORT Ucad::ErrorStatus setFilingOption(UcDbField::FilingOption nOption);

    UCDB_PORT const ZTCHAR  * evaluatorId    (void) const;
    UCDB_PORT Ucad::ErrorStatus setEvaluatorId(const ZTCHAR * pszEvaluatorId);
    bool            isTextField             (void) const;
    Ucad::ErrorStatus convertToTextField    (void);

    UCDB_PORT const ZTCHAR * getFieldCode   (UcDbField::FieldCodeFlag nFlag,
                                             UcArray<UcDbField*>* pChildFields = NULL, 
                                             UcDb::OpenMode mode = UcDb::kForRead) const;
    UCDB_PORT Ucad::ErrorStatus getFieldCode(ZTCHAR*& pszFieldCode,
                                             UcDbField::FieldCodeFlag nFlag,
                                             UcArray<UcDbField*>* pChildFields = NULL, 
                                             UcDb::OpenMode mode = UcDb::kForRead) const;
    UCDB_PORT Ucad::ErrorStatus setFieldCode(const ZTCHAR* pszFieldCode,
                                             UcDbField::FieldCodeFlag nFlag = (UcDbField::FieldCodeFlag) 0,
                                             UcDbFieldArray* pChildFields = NULL);

    UCDB_PORT int   childCount              (void) const;
    UCDB_PORT Ucad::ErrorStatus getChild    (int iIndex, 
                                             UcDbField*& pField, 
                                             UcDb::OpenMode mode);

    UCDB_PORT const ZTCHAR * getFormat       (void) const;
    UCDB_PORT Ucad::ErrorStatus getFormat   (ZTCHAR*& pszFormat) const;
    UCDB_PORT Ucad::ErrorStatus setFormat   (const ZTCHAR* pszFormat);

    UCDB_PORT Ucad::ErrorStatus evaluate    (int nContext, 
                                             UcDbDatabase* pDb, 
                                             int* pNumFound     = NULL,
                                             int* pNumEvaluated = NULL);
    UCDB_PORT UcValue::DataType dataType    (void) const;

    UCDB_PORT const ZTCHAR * getValue        (void) const;
    UCDB_PORT Ucad::ErrorStatus getValue    (ZTCHAR*& pszValue) const;
    UCDB_PORT Ucad::ErrorStatus getValue    (UcValue& value) const;
    UCDB_PORT Ucad::ErrorStatus getValue    (UcFdFieldValue& value) const;

    UCDB_PORT bool  hasHyperlink            (void) const;
    UCDB_PORT Ucad::ErrorStatus getHyperlink(UcHyperlink& hlink) const;
    UCDB_PORT Ucad::ErrorStatus getHyperlink(ZTCHAR** pszName,
                                             ZTCHAR** pszDescription,
                                             ZTCHAR** pszSubLocation,
                                             ZTCHAR** pszDisplayString,
                                             ZSoft::Int32* pFlag) const;
    UCDB_PORT Ucad::ErrorStatus setHyperlink(const UcHyperlink& hlink);
    UCDB_PORT Ucad::ErrorStatus setHyperlink(const ZTCHAR* pszName,
                                             const ZTCHAR* pszDescription,
                                             const ZTCHAR* pszSubLocation = NULL);
    UCDB_PORT Ucad::ErrorStatus setHyperlink(const ZTCHAR* pszName,
                                             const ZTCHAR* pszDescription,
                                             const ZTCHAR* pszSubLocation,
                                             ZSoft::Int32 lFlag);
    UCDB_PORT Ucad::ErrorStatus removeHyperlink(void);

    UCDB_PORT Ucad::ErrorStatus getData     (const ZTCHAR* pszKey,
                                             UcValue* pData) const;
    UCDB_PORT Ucad::ErrorStatus setData     (const ZTCHAR* pszKey,
                                             const UcValue* pData);
    UCDB_PORT Ucad::ErrorStatus setData     (const ZTCHAR* pszKey,
                                             const UcValue* pData,
                                             bool bRecursive);

public:
    
    UCDB_PORT virtual Ucad::ErrorStatus dwgInFields (UcDbDwgFiler* pFiler);
    UCDB_PORT virtual Ucad::ErrorStatus dwgOutFields(UcDbDwgFiler* pFiler) const;
    UCDB_PORT virtual Ucad::ErrorStatus dxfInFields (UcDbDxfFiler* pFiler);
    UCDB_PORT virtual Ucad::ErrorStatus dxfOutFields(UcDbDxfFiler* pFiler) const;
    UCDB_PORT virtual Ucad::ErrorStatus subClose();
};

UCDB_PORT UcFdFieldEngine* ucdbGetFieldEngine(void);
UCDB_PORT bool      ucdbGetFieldMarkers     (const ZTCHAR*& pszPrefix,
                                             const ZTCHAR*& pszSuffix);
UCDB_PORT bool      ucdbHasFields           (const ZTCHAR * pszText);
UCDB_PORT bool      ucdbFindField           (const ZTCHAR * pszText,
                                             int iSearchFrom, 
                                             int& nStartPos, 
                                             int& nEndPos);
UCDB_PORT Ucad::ErrorStatus ucdbEvaluateFields(const UcDbObjectId& objId, 
                                             int nContext, 
                                             const ZTCHAR* pszPropName  = NULL,
                                             UcDbDatabase* pDb          = NULL, 
                                             UcFd::EvalFields nEvalFlag = UcFd::kEvalRecursive,
                                             int* pNumFound             = NULL,
                                             int* pNumEvaluated         = NULL);
UCDB_PORT Ucad::ErrorStatus ucdbEvaluateFields(const UcDbObjectId& objId,
                                             int nContext,
                                             const UcDbObjectIdArray* pFieldsToEvaluate,
                                             const ZTCHAR* pszEvaluatorId,
                                             UcDbDatabase* pDb,
                                             UcFd::EvalFields nEvalFlag,
                                             int* pNumFound,
                                             int* pNumEvaluated);
UCDB_PORT Ucad::ErrorStatus ucdbEvaluateFields(const UcDbObjectIdArray& objIds,
                                             int nContext,
                                             const ZTCHAR* pszPropName  = NULL,
                                             UcDbDatabase* pDb          = NULL, 
                                             UcFd::EvalFields nEvalFlag = UcFd::kEvalRecursive,
                                             int* pNumFound             = NULL,
                                             int* pNumEvaluated         = NULL);
UCDB_PORT Ucad::ErrorStatus ucdbEvaluateFields(const UcDbObjectIdArray& objIds,
                                             int nContext,
                                             const UcDbObjectIdArray* pFieldsToEvaluate,
                                             const ZTCHAR* pszEvaluatorId,
                                             UcDbDatabase* pDb,
                                             UcFd::EvalFields nEvalFlag,
                                             int* pNumFound,
                                             int* pNumEvaluated);
UCDB_PORT Ucad::ErrorStatus ucdbConvertFieldsToText(UcDbDatabase* pDb,
                                             const UcStringArray* pEvalIds,
                                             UcFd::ConvertFieldToText nOption);
UCDB_PORT Ucad::ErrorStatus ucdbConvertFieldsToText(const UcDbObjectIdArray& objIds,
                                             const UcStringArray* pEvalIds,
                                             UcFd::ConvertFieldToText nOption);
UCDB_PORT Ucad::ErrorStatus ucdbMakeFieldCode(const ZTCHAR * pszFieldExpr,
                                             ZTCHAR*& pszFieldCode);
UCDB_PORT Ucad::ErrorStatus ucdbMakeFieldCode(const ZTCHAR * pszFieldExpr,
                                             ZTCHAR*& pszFieldCode,
                                             const ZTCHAR * pszEvalId,
                                             const ZTCHAR * pszFormat,
                                             const UcHyperlink* pHyperlink);
